#ifndef FUNCTIONS_H__
#define FUNCTIONS_H__

/**
 * Compute inv(x) mod m (small numbers)
 *
 * @pre gcd(x,m)=1
 */
int inv_mod(int x, int m);

/**
 * Compute inverse modulo using OpenSSL bn (big numbers) library
 *
 * @ret 0 in case of success
 */
int inv_mod_bn(const char *x, const char *m, char **rez);

/**
 * Compute a^p mod m
 *
 * @ret 0 in case of success
 */
int exp_mod_bn(const char *a, const char *p, const char *m, char **rez);

/* Compute greatest common divisor */
int gcd(int a, int b );

/* Recursive function for gcd */
int gcd_rec(int a, int b );

/* /brief
 * Chinese reminder theorem solver
 *
 *	xi==ai mod mi ,
 *
 * 	- check preconditions ( (mi, mj) = 1 )
 * 	- compute X  ( x=sum(ai*Mi*Ni) mod M, Mi=M/mi, M=prod(mi), Mi*Ni==1 (mod  mi) )
 * 	- verify result
 * 	- return X
 *
 * @param a[IN] - input array of k elements
 * @param m[IN] - input array of k elements
 * @param k[IN] - number of elements
 * @param x[out] - computed result
 * @param M[out] - M=prod(mi)
 *
 * @ret - return code; 0 if OK
 *
 */
int crt(int* a, int* m, int k, int* x, int* M) ;

/* crt with OpenSSL BIGNUMs */
int crt_bn(char **a, char **m, int k, char **x, char **rez_M);

#endif // FUNCTIONS_H__
